package com.lefevre.cms.service.question.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lefevre.cms.bean.platformShare.QuestionRewardPlatformShare;
import com.lefevre.cms.bean.question.Answer;
import com.lefevre.cms.bean.question.AnswerReply;
import com.lefevre.cms.bean.topic.Reply;
import com.lefevre.cms.mapper.AnswerMapper;
import com.lefevre.cms.mapper.AnswerReplyMapper;
import com.lefevre.cms.mapper.QuestionRewardPlatformShareMapper;
import com.lefevre.cms.mapper.ReplyMapper;
import com.lefevre.cms.service.besa.DaoSupport;
import com.lefevre.cms.service.platformShare.PlatformShareService;
import com.lefevre.cms.service.question.AnswerService;
import com.lefevre.cms.service.question.QuestionService;
import com.lefevre.cms.service.user.UserService;
import com.lefevre.cms.web.action.SystemException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 答案管理实现类
 *
 * @author Lefevre
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class AnswerServiceImpl extends DaoSupport<Answer> implements AnswerService {

    @Resource
    QuestionService questionService;
    @Resource
    UserService userService;
    @Resource
    PlatformShareService platformShareService;
    @Resource
    private AnswerMapper baseMapper;
    @Resource
    private ReplyMapper replyMapper;
    @Resource
    private AnswerReplyMapper answerReplyMapper;
    @Resource
    private QuestionRewardPlatformShareMapper questionRewardPlatformShareMapper;

    /**
     * 根据答案Id查询答案
     *
     * @param answerId 答案Id
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public Answer findByAnswerId(Long answerId) {
        return baseMapper.selectById(answerId);
    }

    /**
     * 根据答案Id集合查询答案
     *
     * @param answerIdList 答案Id集合
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public List<Answer> findByAnswerIdList(List<Long> answerIdList) {
        return baseMapper.selectBatchIds(answerIdList);
    }

    /**
     * 根据用户名称查询回答数量
     *
     * @param userName 用户名称
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public Long findAnswerCountByUserName(String userName) {
        return baseMapper.selectCount(new LambdaQueryWrapper<Answer>()
                .eq(Answer::getUserName, userName)
                .eq(Answer::getStatus, 20));
    }

    /**
     * 根据答案Id查询答案在表的第几行
     *
     * @param answerId   答案Id
     * @param questionId 问题Id
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public Long findRowByAnswerId(Long answerId, Long questionId) {
        return baseMapper.selectCount(new LambdaQueryWrapper<Answer>()
                .le(Answer::getId, answerId)
                .eq(Answer::getQuestionId, questionId)
                .orderByAsc(Answer::getPostTime));
    }

    /**
     * 根据答案Id查询答案在表的第几行
     *
     * @param answerId   答案Id
     * @param questionId 问题Id
     * @param status     状态
     * @param sort       按发表时间排序 1.desc 2.asc
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public Long findRowByAnswerId(Long answerId, Long questionId, Integer status, Integer sort) {
        LambdaQueryWrapper<Answer> wrapper = new LambdaQueryWrapper<>();
        if (sort.equals(1)) {
            wrapper.ge(Answer::getId, answerId);
            wrapper.orderByDesc(Answer::getPostTime);
        } else {
            wrapper.le(Answer::getId, answerId);
            wrapper.orderByAsc(Answer::getPostTime);
        }
        wrapper.eq(Answer::getQuestionId, questionId);
        wrapper.eq(Answer::getStatus, status);
        return baseMapper.selectCount(wrapper);
    }

    /**
     * 分页查询答案内容
     *
     * @param firstIndex
     * @param maxResult
     * @param userName   用户名称
     * @param isStaff    是否为员工
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public List<String> findAnswerContentByPage(int firstIndex, int maxResult, String userName, boolean isStaff) {
        //key:话题Id  value:话题内容
        List<String> contentList = new ArrayList<>();
        LambdaQueryWrapper<Answer> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Answer::getUserName, userName);
        wrapper.eq(Answer::getIsStaff, isStaff);
        Page<Answer> answerPage = baseMapper.selectPage(new Page<>(firstIndex, maxResult), wrapper);

        for (Answer record : answerPage.getRecords()) {
            contentList.add(record.getContent());
        }
        return contentList;
    }


    /**
     * 保存答案
     *
     * @param answer
     */
    public void saveAnswer(Answer answer) {
        baseMapper.insert(answer);
        questionService.addAnswerTotal(answer.getQuestionId(), 1L);
    }


    /**
     * 修改答案
     *
     * @param answerId 答案Id
     * @param content  内容
     * @param status   状态
     * @param userName 用户名称
     * @return
     */
    public Integer updateAnswer(Long answerId, String content, Integer status, String userName) {
        Answer answer = baseMapper.selectById(answerId);
        answer.setContent(content);
        answer.setUserName(userName);
        answer.setStatus(status);

        return baseMapper.updateById(answer);
    }

    /**
     * 修改答案
     *
     * @param answerId       答案Id
     * @param content        内容
     * @param status         状态
     * @param lastUpdateTime 最后修改时间
     * @param userName       用户名称
     * @return
     */
    public Integer updateAnswer(Long answerId, String content, Integer status, Date lastUpdateTime, String userName) {
        Answer answer = baseMapper.selectById(answerId);
        answer.setContent(content);
        answer.setUserName(userName);
        answer.setStatus(status);
        answer.setLastUpdateTime(lastUpdateTime);

        return baseMapper.updateById(answer);
    }

    /**
     * 修改答案状态
     *
     * @param answerId 答案Id
     * @param status   状态
     * @return
     */
    public int updateAnswerStatus(Long answerId, Integer status) {
        return baseMapper.update(null, new LambdaUpdateWrapper<Answer>()
                .set(Answer::getStatus, status)
                .eq(Answer::getId, answerId));
    }


    /**
     * 采纳答案
     *
     * @param questionId                        问题Id
     * @param answerId                          答案Id
     * @param changeAdoption                    是否更改采纳答案
     * @param cancelAdoptionUserName            取消采纳用户名称
     * @param cancelAdoptionPointLogObject      取消采纳用户退还悬赏积分日志
     * @param cancelAdoptionUserNameShareAmount 取消采纳用户退还分成金额
     * @param cancelAdoptionPaymentLogObject    取消采纳用户退还悬赏金额日志
     * @param userName                          回答的用户名称
     * @param point                             扣减用户积分
     * @param pointLogObject                    积分日志
     * @param amount                            扣减用户预存款
     * @param paymentLogObject                  支付日志
     * @param questionRewardPlatformShare       平台分成
     * @return
     */
    public int updateAdoptionAnswer(Long questionId, Long answerId, boolean changeAdoption, String cancelAdoptionUserName, Object cancelAdoptionPointLogObject, BigDecimal cancelAdoptionUserNameShareAmount, Object cancelAdoptionPaymentLogObject,
                                    String userName, Long point, Object pointLogObject, BigDecimal amount, Object paymentLogObject, QuestionRewardPlatformShare questionRewardPlatformShare) {
        //先设置所有答案为不采纳
        baseMapper.update(null, new LambdaUpdateWrapper<Answer>()
                .set(Answer::getAdoption, false)
                .eq(Answer::getQuestionId, questionId));

        int i = baseMapper.update(null, new LambdaUpdateWrapper<Answer>()
                .set(Answer::getAdoption, true)
                .eq(Answer::getId, answerId));
        if (i > 0) {
            //修改问题的采纳答案Id
            questionService.updateAdoptionAnswerId(questionId, answerId);
            //如果是更改采纳
            if (changeAdoption) {
                //悬赏退还
                this.rewardReturn(cancelAdoptionUserName, cancelAdoptionPointLogObject, cancelAdoptionUserNameShareAmount, cancelAdoptionPaymentLogObject, point);
                //悬赏支付
                this.rewardPayment(userName, point, pointLogObject, amount, paymentLogObject);

                //删除旧的平台分成
                platformShareService.deleteQuestionRewardPlatformShare(questionId, cancelAdoptionUserName);
                //保存新的平台分成
                //平台分成
                if (questionRewardPlatformShare != null) {
                    questionRewardPlatformShareMapper.insert(questionRewardPlatformShare);
                }
            } else {
                //悬赏支付
                this.rewardPayment(userName, point, pointLogObject, amount, paymentLogObject);
                //平台分成
                if (questionRewardPlatformShare != null) {
                    questionRewardPlatformShareMapper.insert(questionRewardPlatformShare);
                }
            }
        }
        return i;
    }


    /**
     * 悬赏支付
     *
     * @param userName         用户名称
     * @param point            扣减用户积分
     * @param pointLogObject   积分日志
     * @param amount           扣减用户预存款
     * @param paymentLogObject 支付日志
     */
    private void rewardPayment(String userName, Long point, Object pointLogObject, BigDecimal amount, Object paymentLogObject) {
        if (point != null && point > 0L) {//积分
            //增加用户积分
            userService.addUserPoint(userName, point, pointLogObject);
        }
        if (amount != null && amount.compareTo(new BigDecimal("0")) > 0) {//余额
            //增加用户预存款
            userService.addUserDeposit(userName, amount, paymentLogObject);
        }
    }


    /**
     * 悬赏退还
     */
    private void rewardReturn(String cancelAdoptionUserName, Object cancelAdoptionPointLogObject, BigDecimal cancelAdoptionUserNameShareAmount, Object cancelAdoptionPaymentLogObject, Long point) {
        if (cancelAdoptionPointLogObject != null && point != null && point > 0L) {//积分
            //扣减用户积分
            int i = userService.subtractUserPoint(cancelAdoptionUserName, point, cancelAdoptionPointLogObject);
            if (i == 0) {
                throw new SystemException("扣减积分失败");
            }
        }
        if (cancelAdoptionPaymentLogObject != null && cancelAdoptionUserNameShareAmount != null && cancelAdoptionUserNameShareAmount.compareTo(new BigDecimal("0")) > 0) {//余额
            //扣减用户预存款
            int i = userService.subtractUserDeposit(cancelAdoptionUserName, cancelAdoptionUserNameShareAmount, cancelAdoptionPaymentLogObject);
            if (i == 0) {
                throw new SystemException("扣减预存款失败");
            }
        }
    }

    /**
     * 取消采纳答案
     *
     * @param questionId                        问题Id
     * @param cancelAdoptionUserName            取消采纳用户名称
     * @param cancelAdoptionPointLogObject      取消采纳用户退还悬赏积分日志
     * @param cancelAdoptionUserNameShareAmount 取消采纳用户退还分成金额
     * @param cancelAdoptionPaymentLogObject    取消采纳用户退还悬赏金额日志
     * @param point                             扣减用户积分
     * @return
     */
    public int updateCancelAdoptionAnswer(Long questionId, String cancelAdoptionUserName, Object cancelAdoptionPointLogObject, BigDecimal cancelAdoptionUserNameShareAmount, Object cancelAdoptionPaymentLogObject, Long point) {
        //先设置所有答案为不采纳
        baseMapper.update(null, new LambdaUpdateWrapper<Answer>()
                .set(Answer::getAdoption, false)
                .eq(Answer::getQuestionId, questionId));
        //修改问题的采纳答案Id
        int i = questionService.updateAdoptionAnswerId(questionId, 0L);
        if (i > 0) {
            //悬赏退还
            this.rewardReturn(cancelAdoptionUserName, cancelAdoptionPointLogObject, cancelAdoptionUserNameShareAmount, cancelAdoptionPaymentLogObject, point);
            //删除平台分成
            platformShareService.deleteQuestionRewardPlatformShare(questionId, cancelAdoptionUserName);
        }
        return i;
    }


    /**
     * 删除答案
     *
     * @param questionId                        问题Id
     * @param answerId                          答案Id
     * @param cancelAdoptionUserName            取消采纳用户名称
     * @param cancelAdoptionPointLogObject      取消采纳用户退还悬赏积分日志
     * @param cancelAdoptionUserNameShareAmount 取消采纳用户退还分成金额
     * @param cancelAdoptionPaymentLogObject    取消采纳用户退还悬赏金额日志
     * @param point                             扣减用户积分
     * @return
     */
    public Integer deleteAnswer(Long questionId, Long answerId, String cancelAdoptionUserName, Object cancelAdoptionPointLogObject, BigDecimal cancelAdoptionUserNameShareAmount, Object cancelAdoptionPaymentLogObject, Long point) {
        //删除答案
        int i = baseMapper.deleteById(answerId);
        if (i > 0) {
            //悬赏退还
            this.rewardReturn(cancelAdoptionUserName, cancelAdoptionPointLogObject, cancelAdoptionUserNameShareAmount, cancelAdoptionPaymentLogObject, point);
            if (cancelAdoptionUserName != null) {
                //修改问题的采纳答案Id
                questionService.updateAdoptionAnswerId(questionId, 0L);
                //删除平台分成
                platformShareService.deleteQuestionRewardPlatformShare(questionId, cancelAdoptionUserName);
            }
        }
        //删除答案回复
        answerReplyMapper.delete(new LambdaUpdateWrapper<AnswerReply>().eq(AnswerReply::getAnswerId, answerId));
        questionService.subtractAnswerTotal(questionId, 1L);
        return i;
    }


    /**
     * 根据用户名称集合删除答案
     *
     * @param userNameList 用户名称集合
     * @return
     */
    public Integer deleteAnswer(List<String> userNameList) {
        return baseMapper.delete(new LambdaUpdateWrapper<Answer>()
                .in(Answer::getUserName, userNameList)
                .eq(Answer::getIsStaff, false));
    }

    /**
     * 标记删除答案
     *
     * @param answerIdId 答案Id
     * @param constant   常数 例如 "110.待审核用户删除" 则加上100
     * @return
     */
    public Integer markDeleteAnswer(Long answerId, Integer constant) {
        Answer answer = baseMapper.selectOne(new LambdaQueryWrapper<Answer>().eq(Answer::getId, answerId).lt(Answer::getStatus, constant));
        answer.setStatus(answer.getStatus() + constant);

        return baseMapper.updateById(answer);
    }

    /**
     * 查询待审核答案数量
     *
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public Long auditAnswerCount() {
        return baseMapper.selectCount(new LambdaQueryWrapper<Answer>().eq(Answer::getStatus, 10));
    }


    /**--------------------------------------- 回复 ---------------------------------------**/


    /**
     * 添加回复
     *
     * @param answerReply
     */
    public void saveReply(AnswerReply answerReply) {
        answerReplyMapper.insert(answerReply);
    }

    /**
     * 根据答案Id查询回复
     *
     * @param answerId 答案Id
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public List<AnswerReply> findReplyByAnswerId(Long answerId) {
        return answerReplyMapper.selectList(new LambdaQueryWrapper<AnswerReply>().eq(AnswerReply::getAnswerId, answerId));
    }

    /**
     * 根据答案Id集合查询回复
     *
     * @param answerIdList 答案Id集合
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public List<AnswerReply> findReplyByAnswerId(List<Long> answerIdList) {
        return answerReplyMapper.selectList(new LambdaQueryWrapper<AnswerReply>().in(AnswerReply::getAnswerId, answerIdList));
    }

    /**
     * 根据答案Id集合查询回复
     *
     * @param answerIdList 答案Id集合
     * @param status       状态
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public List<AnswerReply> findReplyByAnswerId(List<Long> answerIdList, Integer status) {
        return answerReplyMapper.selectList(new LambdaQueryWrapper<AnswerReply>()
                .in(AnswerReply::getAnswerId, answerIdList)
                .eq(AnswerReply::getStatus, status));
    }


    /**
     * 根据答案回复Id查询答案回复
     *
     * @param answerReplyId 答案回复Id
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public AnswerReply findReplyByReplyId(Long answerReplyId) {
        return answerReplyMapper.selectById(answerReplyId);
    }

    /**
     * 根据答案回复Id集合查询答案回复
     *
     * @param answerReplyIdList 答案Id集合
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public List<AnswerReply> findByAnswerReplyIdList(List<Long> answerReplyIdList) {
        return answerReplyMapper.selectBatchIds(answerReplyIdList);
    }
    /**
     * 分页查询回复
     * @param userName 用户名称
     * @param postTime 回复发表时间
     * @param firstIndex
     * @param maxResult
     * @return

     @Transactional(readOnly=true,propagation=Propagation.NOT_SUPPORTED) public List<Reply> findReplyByPage(String userName,Date postTime,int firstIndex, int maxResult){
     String sql = "select o from Reply o where o.userName=?1 and o.postTime>?2";
     Query query = em.createQuery(sql);
     query.setParameter(1, userName);
     query.setParameter(2, postTime);
     //索引开始,即从哪条记录开始
     query.setFirstResult(firstIndex);
     //获取多少条数据
     query.setMaxResults(maxResult);

     List<Reply> replyList = query.getResultList();
     return replyList;
     }*/

    /**
     * 修改回复
     *
     * @param answerReplyId 回复Id
     * @param content       回复内容
     * @param userName      用户名称
     * @param status        状态
     * @return
     */
    public Integer updateReply(Long answerReplyId, String content, String userName, Integer status) {
        AnswerReply answerReply = answerReplyMapper.selectById(answerReplyId);
        answerReply.setContent(content);
        answerReply.setUserName(userName);
        answerReply.setStatus(status);

        return answerReplyMapper.updateById(answerReply);
    }

    /**
     * 修改回复
     *
     * @param replyId        回复Id
     * @param content        回复内容
     * @param userName       用户名称
     * @param status         状态
     * @param lastUpdateTime 最后修改时间
     * @return
     */
    public Integer updateReply(Long replyId, String content, String userName, Integer status, Date lastUpdateTime) {
        AnswerReply answerReply = answerReplyMapper.selectById(replyId);
        answerReply.setContent(content);
        answerReply.setUserName(userName);
        answerReply.setStatus(status);
        answerReply.setLastUpdateTime(lastUpdateTime);

        return answerReplyMapper.updateById(answerReply);
    }

    /**
     * 修改回复状态
     *
     * @param answerReplyId 回复Id
     * @param status        状态
     * @return
     */
    public int updateReplyStatus(Long answerReplyId, Integer status) {
        return answerReplyMapper.update(null, new LambdaUpdateWrapper<AnswerReply>()
                .set(AnswerReply::getStatus, status)
                .eq(AnswerReply::getId, answerReplyId));
    }

    /**
     * 标记删除回复
     *
     * @param replyId  回复Id
     * @param constant 常数 例如 "110.待审核用户删除" 则加上100
     * @return
     */
    public Integer markDeleteReply(Long replyId, Integer constant) {
        AnswerReply answerReply = answerReplyMapper.selectOne(new LambdaQueryWrapper<AnswerReply>().eq(AnswerReply::getAnswerId, replyId)
                .lt(AnswerReply::getStatus, constant));
        answerReply.setStatus(answerReply.getStatus() + constant);

        return answerReplyMapper.updateById(answerReply);
    }

    /**
     * 删除回复
     *
     * @param answerReplyId 回复Id
     * @return
     */
    public Integer deleteReply(Long answerReplyId) {
        return answerReplyMapper.deleteById(answerReplyId);
    }

    /**
     * 根据用户名称集合删除答案回复
     *
     * @param userNameList 用户名称集合
     * @return
     */
    public Integer deleteAnswerReply(List<String> userNameList) {
        //删除回复
        return answerReplyMapper.delete(new LambdaUpdateWrapper<AnswerReply>()
                .in(AnswerReply::getUserName, userNameList)
                .eq(AnswerReply::getIsStaff, false));
    }

    /**
     * 查询待审核回复数量
     *
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public Long auditReplyCount() {
        return replyMapper.selectCount(new LambdaQueryWrapper<Reply>().eq(Reply::getStatus, 10));
    }
}
